package com.xiumu.service.sys.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiumu.common.core.constants.XiuMuConst;
import com.xiumu.common.core.enums.YesNo;
import com.xiumu.common.core.exception.user.RoleException;
import com.xiumu.common.core.page.PageQuery;
import com.xiumu.common.core.utils.AssertUtil;
import com.xiumu.dao.sys.RoleDao;
import com.xiumu.pojo.sys.dto.RoleDTO;
import com.xiumu.pojo.sys.entity.Role;
import com.xiumu.pojo.sys.entity.RoleAuth;
import com.xiumu.pojo.sys.entity.UserRole;
import com.xiumu.pojo.sys.query.RoleQuery;
import com.xiumu.service.sys.RoleAuthService;
import com.xiumu.service.sys.RoleService;
import com.xiumu.service.sys.UserRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 角色 Service 业务层处理
 *
 * @author XiuMu
 * @date 2022-07-16 17:25:52
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleDao, Role> implements RoleService {

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RoleAuthService roleAuthService;

    @Override
    public Page<Role> listPage(PageQuery<RoleQuery, Role> pageQuery) {
        setRoleQuery(pageQuery.getCondition());
        return this.baseMapper.selectPage(pageQuery.toPage(), pageQuery.getCondition());
    }

    @Override
    public List<Role> listByRole(RoleQuery role) {
        setRoleQuery(role);
        return this.baseMapper.selectByRole(role);
    }

    @Override
    public List<String> listRoleCodeByUserId(Long userId) {
        return listByUserId(userId).stream().map(Role::getRoleCode).toList();
    }

    @Override
    @Transactional
    public boolean create(RoleDTO roleDTO) {
        Role role = getByRoleCode(roleDTO.getRoleCode());
        AssertUtil.isNull(role, RoleException.CODE_EXIT);
        role = BeanUtil.toBean(roleDTO, Role.class);
        return this.save(role);
    }

    @Override
    @Transactional
    public boolean updateById(RoleDTO roleDTO, Long id) {
        Role role = new Role().setRoleName(roleDTO.getRoleName()).setRoleDesc(roleDTO.getRoleDesc());
        role.setId(id);
        return updateById(role);
    }

    @Override
    public boolean deleteById(Long id) {
        // 该角色有用户绑定就不可被删除
        List<UserRole> userRoleList = userRoleService.list(new LambdaQueryWrapper<UserRole>().eq(UserRole::getRoleId, id));
        AssertUtil.isTrue(CollUtil.isEmpty(userRoleList), RoleException.ROLE_HAS_BIND);
        // 没有绑定，就直接删除
        roleAuthService.remove(new LambdaQueryWrapper<RoleAuth>().eq(RoleAuth::getRoleId, id));
        return this.removeById(id);
    }

    @Override
    public Role getByRoleCode(String roleCode) {
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<Role>()
                .eq(Role::getRoleCode, roleCode)
                .eq(Role::getDeleteFlag, YesNo.NO);
        return getOne(queryWrapper);
    }

    @Override
    public List<Role> listByUserId(Long userId) {
        return this.baseMapper.selectByUserId(userId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAuthByRoleId(List<Long> authList, Long roleId) {
        if (CollUtil.isNotEmpty(authList)){
            List<RoleAuth> roleAuthList = roleAuthService.listByRoleId(roleId);
            // 过滤出需要删除的权限
            List<Long> deleteIdList = roleAuthList.stream()
                    .filter(roleAuth -> !authList.contains(roleAuth.getAuthId()))
                    .map(RoleAuth::getId)
                    .toList();
            // 过滤出需要新增的权限
            authList.removeIf(authId -> roleAuthList.stream().anyMatch(roleAuth -> roleAuth.getAuthId().equals(authId)));
            List<RoleAuth> addList = authList.stream().map(auth -> new RoleAuth(roleId, auth)).toList();
            roleAuthService.removeBatchByIds(deleteIdList);
            roleAuthService.saveBatch(addList);
        }else {
            roleAuthService.remove(new LambdaQueryWrapper<RoleAuth>().eq(RoleAuth::getRoleId, roleId));
        }
        return true;
    }

    /**
     * 重写 list 方法，查询未逻辑删除的记录
     *
     * @return
     */
    @Override
    public List<Role> list() {
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<Role>().eq(Role::getDeleteFlag, YesNo.NO);
        return this.baseMapper.selectList(queryWrapper);
    }

    /**
     * 重写 list 方法，查询未逻辑删除的记录
     *
     * @return
     */
    public List<Role> list(LambdaQueryWrapper<Role> queryWrapper) {
        if (ObjectUtil.isNull(queryWrapper)) {
            queryWrapper = new LambdaQueryWrapper<Role>();
        }
        queryWrapper.eq(Role::getDeleteFlag, YesNo.NO);
        return this.baseMapper.selectList(queryWrapper);
    }

    /**
     * 给查询条件添加 supperAdminFlag 条件
     * 只有超级管理员才能可能看到超级管理员角色
     * @param query 查询条件
     */
    private void setRoleQuery(RoleQuery query){
        // 判断是否有超级管理员角色
        if (query == null){
            query = new RoleQuery();
        }
        query.setSupperAdminFlag(StpUtil.hasRole(XiuMuConst.SUPPER_ADMIN_ROLE_CODE));
    }
}
